/*
 * MIT License
 *
 * Copyright (c) 2020 wen.gu <454727014@qq.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

 /***************************************************************************
 * Name: lz4_encoder.c
 *
 * Purpose: implementation a encoder with lz4 compress
 *
 * Developer:
 *   wen.gu , 2022-03-04
 *
 * TODO:
 *
 ***************************************************************************/

 /******************************************************************************
 **    INCLUDES
 ******************************************************************************/

#include "lz4_encoder.h"

#include <stdio.h>
#include <string.h>
/******************************************************************************
 **    MACROS
 ******************************************************************************/

/******************************************************************************
 **    VARIABLE DEFINITIONS
 ******************************************************************************/

/******************************************************************************
 **    inner FUNCTION DEFINITIONS
 ******************************************************************************/

/******************************************************************************
 **    FUNCTION DEFINITIONS
 ******************************************************************************/

Lz4Encoder::Lz4Encoder()
{
    encoder_hc_ = LZ4_createStreamHC();
}

Lz4Encoder::~Lz4Encoder()
{
    if (encoder_hc_)
    {
        LZ4_freeStreamHC(encoder_hc_);
    }

    if (src_data_buf_)
    {
        delete[] src_data_buf_;
    }

    if (dst_buf_)
    {
        delete[] dst_buf_;
    }

    //printf("[%s.%d]===>:\n", __FUNCTION__, __LINE__);
}

bool Lz4Encoder::setConfigure(uint32_t src_block_size)
{
    if (!is_initialized_)
    {
        src_block_size_ = src_block_size;
        src_data_buf_ = new uint8_t[src_block_size * LZ4_ENC_SRC_BUF_CNT];
        src_buf_[0] = src_data_buf_;
        src_buf_[1] = src_data_buf_ + src_block_size;
        dst_buf_ = new uint8_t[get_dst_buffer_size()];
        dst_block_size_ = get_dst_buffer_size();   
        is_initialized_ = true;     
    }

    return true;
}

uint8_t* Lz4Encoder::get_src_buffer(uint32_t& src_size)
{
    src_size = src_block_size_;
    return src_buf_[src_buf_dix_++ % 2];
}

uint32_t Lz4Encoder::get_dst_buffer_size()
{
    return LZ4_COMPRESSBOUND(src_block_size_);
}

bool Lz4Encoder::encode(const uint8_t* src, uint32_t src_size , KfaBuffer& out_buf)
{
#if 0    
    const int cmpBytes = LZ4_compress_fast_continue(encoder_,  (const char*)src,   (char*)dst, src_size, dst_size, 1);
    if(cmpBytes <= 0)
    {
        return false;
    }
#else
    setConfigure(src_size);
    uint32_t in_buffer_size = 0;
    uint8_t* src_buf = get_src_buffer(in_buffer_size);

    memcpy(src_buf, src, src_size); /** todo refine me ,donot copy */  

    const int cmpBytes = LZ4_compress_HC_continue(encoder_hc_,  (const char*)src_buf,   (char*)dst_buf_, src_size, dst_block_size_);
    if(cmpBytes <= 0)
    {
        return false;
    }    
#endif
    out_buf.buf = dst_buf_;
    out_buf.size = cmpBytes;
    out_buf.release = [](KfaBuffer& buf)
    {
        //do nothing
    };
    
    return true;    
}
